package com.david.core.view.banner

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.david.core.R
import com.david.core.imgloader.LruImageLoader
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 * 1.banner控件用kotlin重新编写，同时导航条与adapter解耦
 * 2.查看大图列表用banner逻辑实现（itemView使用photoView）
 */
class KtRecyclerBanner: FrameLayout,Handler.Callback {
    /**导航圆点类型 */
    val NAV_DOT: Short = 0

    /**导航条类型 */
    val NAV_BOTTOM_BAR: Short = 1

    /**导航数字类型 */
    val NAV_NUMBER: Short = 2
    var mRecyclerView: RecyclerView

    /**导航条及点的父控件 */
    private var mDotContainer: LinearLayout

    /**导航dot及bar的drawable */
    private lateinit var defaultDrawable: GradientDrawable
    /**导航dot及bar的drawable */
    private  var selectedDrawable: GradientDrawable? = null

    /**导航类型 */
    private var mNavType = 0

    /**导航条宽度 */
    private var mNavBarWidth = 0

    /**导航文本控件 */
    private var mNavNumber: TextView? = null

    /**导航控件底部边距 */
    private val navBottomMargin = 30

    /**默认导航颜色及选中导航颜色 */
    private var defaultColor:Int = 0x75ffffff
    /**默认导航颜色及选中导航颜色 */
    private  var selectColor:Int = -0x97de


    private var mAdapter: KtRecyclerAdapter
//    private var mData: ArrayList<KtBannerEntity> = ArrayList()

    /**圆点大小 */
    private var mDotSize = 0

    /**手指触屏位置 */
    private var startX = 0
    /**手指触屏位置 */
    private  var startY:Int = 0

    /**当前滚动位置 */
    private var currentIndex = 0

    /**是否滚动 */
    private var isPlaying = false

    private var tempCurrent = 0

    private var navChildCount = 0

    @SuppressLint("HandlerLeak")
    private val mHandler: Handler = Handler(Looper.getMainLooper(), this)

    override fun handleMessage(msg: Message): Boolean {
        currentIndex = if (currentIndex >= mAdapter.mData.size - 1) 1 else ++currentIndex
        if (currentIndex >= mAdapter.mData.size) {
            currentIndex %= mAdapter.mData.size
        }

        mRecyclerView.smoothScrollToPosition(currentIndex)
        mHandler.sendEmptyMessageDelayed(0, 3000)
        return true
    }

    constructor(context: Context):this(context, null)

    constructor(context: Context, attrs: AttributeSet?):this(context, attrs, 0)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int):super(context, attrs, defStyleAttr) {
        val vpLayoutParams =
            LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        mDotContainer = LinearLayout(context)
        mDotContainer.orientation = LinearLayout.HORIZONTAL
        val linearLayoutParams =
            LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        mDotContainer.gravity = Gravity.CENTER
        linearLayoutParams.setMargins(0, 0, 0, navBottomMargin)
        mDotContainer.setPadding(mDotSize shl 1, mDotSize shl 1, mDotSize shl 1, mDotSize shl 1)
        linearLayoutParams.gravity = Gravity.BOTTOM
        mRecyclerView = RecyclerView(context)
        KtPagerSnapHelper().attachToRecyclerView(mRecyclerView)
        mRecyclerView.layoutManager = LinearLayoutManager(
            context,
            LinearLayoutManager.HORIZONTAL,
            false
        )
        mAdapter = KtRecyclerAdapter()
        mRecyclerView.adapter = mAdapter
        mRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    if (touched) {
                        val first =
                            (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
                        val last =
                            (recyclerView.layoutManager as LinearLayoutManager?)!!.findLastVisibleItemPosition()
                        tempCurrent = if (first == 0) {
                            ((first + last) / 2.0 - 0.1).roundToInt()
                        } else {
                            ((first + last) / 2.0).roundToInt()
                        }
                        if (tempCurrent == mAdapter.mData.size - 1) {
                            tempCurrent = 1
                            mRecyclerView.scrollToPosition(1)
                        } else if (tempCurrent == 0) {
                            tempCurrent = mAdapter.mData.size - 2
                            mRecyclerView.scrollToPosition(mAdapter.mData.size - 2)
                        }
                        if (currentIndex != tempCurrent) {
                            currentIndex = tempCurrent
                            changePoint()
                        }
                        touched = false
                        return
                    }
                    if (currentIndex == mAdapter.mData.size - 1) {
                        mRecyclerView.scrollToPosition(1)
                        currentIndex = 1
                    }
                    changePoint()
                }
            }
        })
        addView(mRecyclerView, vpLayoutParams)
        addView(mDotContainer, linearLayoutParams)
        mNavBarWidth =
            (resources.displayMetrics.widthPixels - 160) / if (mAdapter.mData.size == 0) 5 else mAdapter.mData.size
        mDotSize = (6 * context.resources.displayMetrics.density + 0.5f).toInt()
        initNavView()
        setNavColor(defaultColor, selectColor)


        /*
            TODO 为方便使用没有在属性xml文件中定义属性，如果要使用则直接调用类方法设置比例
            //初始化比例
            TypedArray a = getContext().obtainStyledAttributes(attrs,
                    R.styleable.RatioImageView);
            mIsWidthFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_width_fix_drawable_size_ratio,
                    mIsWidthFitDrawableSizeRatio);
            mIsHeightFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_height_fix_drawable_size_ratio,
                    mIsHeightFitDrawableSizeRatio);
            mHeightRatio = a.getFloat(
                    R.styleable.RatioImageView_height_to_width_ratio, mHeightRatio);
            mWidthRatio = a.getFloat(
                    R.styleable.RatioImageView_width_to_height_ratio, mWidthRatio);
            a.recycle();*/
    }


    fun setOnPagerClickListener(onPagerClickListener: KtOnPagerClickListener?) {
        mAdapter.mPageClickListener = onPagerClickListener
    }

    /**设置是否应该滚动 */
    @Synchronized
    fun setPlaying(playing: Boolean) {
        if (!isPlaying && playing && mAdapter != null && mAdapter.itemCount > 2) {
            mHandler.removeMessages(0)
            mHandler.sendEmptyMessageDelayed(0, 3000)
            isPlaying = true
        } else if (isPlaying && !playing) {
            if (mHandler.hasMessages(0)) {
                mHandler.removeMessages(0)
            }
            isPlaying = false
        }
    }

    /**
     * 设置data需在setColor及setNavType之后
     * @param datas 数据列表
     * @return 数据数量
     */
    fun setDatas(datas: ArrayList<KtBannerEntity>): Int {
        setPlaying(false)
        mDotContainer.removeAllViews()
        if (mAdapter.mData != null) {
            mAdapter.mData.clear()
        } else {
            mAdapter.mData = ArrayList()
        }
        mAdapter.mData.addAll(datas)
        if (mAdapter.mData.size > 1) {
            currentIndex = 1 //设置无限循环播放
            mAdapter!!.notifyDataSetChanged()
            mRecyclerView.scrollToPosition(currentIndex)
            //            for (int i = 0; i < this.mData.size(); i++) {
//                ImageView img = new ImageView(getContext());
//                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//                lp.leftMargin = mDotSize / 2;
//                lp.rightMargin = mDotSize / 2;
//                img.setImageDrawable(i == 0 ? selectedDrawable : defaultDrawable);
//                mDotContainer.addView(img, lp);
//            }
            if (mNavType != NAV_NUMBER.toInt()) {
                for (i in mAdapter.mData.indices) {
                    val img = ImageView(context)
                    val lp = LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT
                    )
                    lp.leftMargin = mDotSize shr 1
                    lp.rightMargin = lp.leftMargin
                    img.setImageDrawable(if (i == 0) selectedDrawable else defaultDrawable)
                    mDotContainer.addView(img, lp)
                }
                navChildCount = mAdapter.mData.size
            } else {
                mNavNumber?.text = String.format(Locale.CHINA, "1/%d", datas.size)
            }
            setPlaying(true)
            mAdapter.mData.add(0, mAdapter.mData[mAdapter.mData.size - 1])
            mAdapter.mData.add(mAdapter.mData[1])
        } else {
            currentIndex = 0
            mAdapter!!.notifyDataSetChanged()
        }
        return mAdapter.mData.size
    }

    private fun initNavView() {
        initNavView(mNavType)
    }

    /**初始化导航类型 */
    private fun initNavView(type: Int) {
        if (type == NAV_DOT.toInt()) {
            if (mDotContainer != null) {
                mDotContainer.visibility = VISIBLE
            }
            if (mNavNumber != null && mNavNumber?.visibility == VISIBLE) {
                mNavNumber?.visibility = GONE
            }
            defaultDrawable = GradientDrawable()
            defaultDrawable.setSize(mDotSize, mDotSize)
            defaultDrawable.cornerRadius = mDotSize.toFloat()
            defaultDrawable.setColor(defaultColor)
            selectedDrawable = GradientDrawable()
            selectedDrawable!!.setSize(mDotSize, mDotSize)
            selectedDrawable!!.cornerRadius = mDotSize.toFloat()
            selectedDrawable!!.setColor(selectColor)
        } else if (type == NAV_BOTTOM_BAR.toInt()) {
            if (mDotContainer != null) {
                mDotContainer.visibility = VISIBLE
            }
            if (mNavNumber != null && mNavNumber?.visibility == VISIBLE) {
                mNavNumber?.visibility = GONE
            }
            defaultDrawable = GradientDrawable()
            defaultDrawable.setSize(mNavBarWidth, mDotSize / 3)
            defaultDrawable.cornerRadius = 0f
            defaultDrawable.setColor(defaultColor)
            selectedDrawable = GradientDrawable()
            selectedDrawable!!.setSize(mNavBarWidth, mDotSize / 3)
            selectedDrawable!!.cornerRadius = 0f
            selectedDrawable!!.setColor(selectColor)
        } else if (type == NAV_NUMBER.toInt()) {
            if (mDotContainer != null) {
                mDotContainer.visibility = GONE
                mDotContainer.removeAllViews()
            }
            if (mNavNumber != null) {
                mNavNumber?.visibility = VISIBLE
                return
            }
            mNavNumber = TextView(context)
            mNavNumber?.layoutParams = LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )

            //设置背景
            val roundRadius = 20 // 8dp 圆角半径
            val fillColor = defaultColor //内部填充颜色
            val gd = GradientDrawable() //创建drawable（动态创建shape）
            gd.setColor(fillColor)
            gd.cornerRadius = roundRadius.toFloat()
            mNavNumber?.background = gd


            //设置边框
//            int strokeColor = Color.parseColor("#2E3135");//边框颜色
//            int strokeWidth = 5; // 3dp 边框宽度
//            gd.setStroke(strokeWidth, strokeColor);
            mNavNumber?.gravity = Gravity.CENTER
            mNavNumber?.setPadding(15, 6, 15, 6)
            mNavNumber?.text = "0/0"
            mNavNumber?.setTextColor(selectColor)
            val params = LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            params.gravity = Gravity.END or Gravity.BOTTOM
            params.bottomMargin = navBottomMargin
            params.rightMargin = navBottomMargin
            addView(mNavNumber, params)
        }
    }


    private var touched = false

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                touched = true
                startX = ev.x.toInt()
                startY = ev.y.toInt()
                parent.requestDisallowInterceptTouchEvent(true)
                setPlaying(false)
            }
            MotionEvent.ACTION_MOVE -> parent.requestDisallowInterceptTouchEvent(
                abs(
                    ev.x
                        .toInt() - startX
                ) > abs(ev.y.toInt() - startY) shl 1
            )
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> setPlaying(true)
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        setPlaying(true)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        setPlaying(false)
    }

    override fun onWindowVisibilityChanged(visibility: Int) {
        if (visibility == GONE) {
            //页面不可见时停止轮播
            setPlaying(false)
        } else if (visibility == VISIBLE) {
            // 恢复可见时开始轮播
            setPlaying(true)
        }
        super.onWindowVisibilityChanged(visibility)
    }

    /**
     * height width ratio,宽高一个固定另一个不固定时才有效果
     */
    private var ratio = 0.5f

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //获取宽度的模式和尺寸
        var widthMeasureSpec = widthMeasureSpec
        var heightMeasureSpec = heightMeasureSpec
        var widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        //获取高度的模式和尺寸
        var heightSize = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)


        //宽确定，高不确定
        if ((widthMode == MeasureSpec.EXACTLY) && (heightMode != MeasureSpec.EXACTLY) && (ratio != 0f)) {
            heightSize = (widthSize * ratio + 0.5f).toInt() //根据宽度和比例计算高度
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)
        } else if (widthMode != MeasureSpec.EXACTLY && (heightMode == MeasureSpec.EXACTLY && ratio.toInt() != 0)) {
            widthSize = (heightSize / ratio + 0.5f).toInt()
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY)
        }

        //必须调用下面的两个方法之一完成onMeasure方法的重写，否则会报错
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    fun setRatio(ratio: Float) {
        this.ratio = ratio
    }

    /**
     * 设置导航点、条、数字颜色，数字颜色不用加selectColor
     * @param defaultColor unSelectColor
     * @param selectColor selectedColor
     */
    fun setNavColor(defaultColor: Int, selectColor: Int) {
        this.defaultColor = defaultColor
        this.selectColor = selectColor
        if (mNavType == NAV_DOT.toInt() || mNavType == NAV_BOTTOM_BAR.toInt()) {
            if (defaultDrawable != null) {
                defaultDrawable.setColor(defaultColor)
            }
            if (selectedDrawable != null) {
                selectedDrawable!!.setColor(selectColor)
            }
        } else {
            if (mNavNumber != null) {
                mNavNumber?.setTextColor(selectColor)
            }
        }
    }

    /**
     * set nav type
     * @param navType type of nav(dot bar or number)
     */
    fun setNavType(navType: Int) {
        if (navType != mNavType) {
            initNavView(navType)
            mNavType = navType
        }
    }

    fun onDestroy() {
        setPlaying(false)
        mHandler.removeMessages(0)
        mRecyclerView.adapter = null
//        mRecyclerView = null
        mAdapter.mData.clear()
//        mData = null
//        mAdapter = null
    }

    private fun changePoint() {
        if (mDotContainer.childCount == 0) {
            return
        }
        if (mNavType == NAV_DOT.toInt() || mNavType == NAV_BOTTOM_BAR.toInt()) {
            if (mDotContainer != null && mDotContainer.childCount > 0) {
                for (i in 0 until navChildCount) {
                    (mDotContainer.getChildAt(i) as ImageView).setImageDrawable(defaultDrawable)
                }
                when (currentIndex) {
                    0 -> {
                        (mDotContainer.getChildAt(navChildCount - 1) as ImageView).setImageDrawable(
                            selectedDrawable
                        )
                    }
                    mAdapter.mData.size - 1 -> {
                        (mDotContainer.getChildAt(0) as ImageView).setImageDrawable(selectedDrawable)
                    }
                    else -> {
//                        (mDotContainer.getChildAt(currentIndex - 1) as ImageView).setImageDrawable(
//                            selectedDrawable
//                        )
                    }
                }
            }
        } else {
            mNavNumber?.text = String.format(Locale.CHINA, "%d/%d", currentIndex, mAdapter.mData.size - 2)
        }
    }
}

class KtRecyclerAdapter :
    RecyclerView.Adapter<RecyclerView.ViewHolder?>(), View.OnClickListener {
    var mPageClickListener: KtOnPagerClickListener? = null

    var mData:ArrayList<KtBannerEntity> = ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val img = ImageView(parent.context)
        val l = RecyclerView.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        img.scaleType = ImageView.ScaleType.CENTER_CROP
        img.layoutParams = l
        img.id = R.id.banner_item
        img.setOnClickListener(this)
        return object : RecyclerView.ViewHolder(img) {}
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        //可自己修改使用哪种方式加载图片
//            ImageView img = (ImageView) holder.itemView.findViewById(R.id.icon);
        LruImageLoader.getInstance().loadCacheImage(
            mData[position % mData.size].url,
            holder.itemView as ImageView
        )
        holder.itemView.tag = position
        //            ((ImageView) holder.itemView).setImageURI(mData.get(position % mData.size()).getUrl());
//            Glide.with(getContext()).load(mData.get(position % mData.size()).getUrl()).placeholder(R.mipmap.ic_launcher).error(R.drawable.arrow_left).into(img);
    }

    override fun getItemCount(): Int {
        return mData.size
    }

    override fun onClick(v: View) {
        if (mPageClickListener != null) {
            mPageClickListener?.onClick(mData[v.tag as Int])
        }
    }
}

open class KtNavigator{

}

class KtPagerSnapHelper: LinearSnapHelper(){
    override fun findTargetSnapPosition(
        layoutManager: RecyclerView.LayoutManager?,
        velocityX: Int,
        velocityY: Int
    ): Int {
        var targetPos = super.findTargetSnapPosition(layoutManager, velocityX, velocityY)
        val currentView = findSnapView(layoutManager)
        if (targetPos != RecyclerView.NO_POSITION && currentView != null) {
            var currentPosition = layoutManager!!.getPosition(currentView)
            val first = (layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
            val last = layoutManager.findLastVisibleItemPosition()
            currentPosition =
                if (targetPos < currentPosition) last else if (targetPos > currentPosition) first else currentPosition
            targetPos =
                if (targetPos < currentPosition) currentPosition - 1 else if (targetPos > currentPosition) currentPosition + 1 else currentPosition
        }
        return targetPos
    }
}

interface KtOnPagerClickListener {
    fun onClick(entity: KtBannerEntity?)
}

interface KtBannerEntity {
    val url: String?
}